/*
 * SA.cpp
 *
 *  Created on: 23/06/2011
 *      Author: daniel
 */

#include "SA.h"
#include "Operator.h"
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;


/**
 * Aplica recocido simulado.
 * @return: Una solucion.
 */
Solution *SA::SimulatedAnnealing(Solution *is, int MaxIter, double alpha,
		double betha, int T, int K, int A) {

	Solution *sOpt = is;
	Solution *sMejor = sOpt;
	Solution *sAct = NULL;
	vector<int*> neighbors;

	int i = 0;
	while (i < MaxIter) {

		int k = 0;
		int a = 0;
		neighbors = Operator::neighbors(sOpt, 1);

		// Recorre la vecindad.
		while (!neighbors.empty() && k < K && a < A) {

			int *mov = neighbors.back();
			neighbors.pop_back();

			sAct = sOpt->swap(mov[0], mov[1]);
			double delta = sAct->cost - sOpt->cost;

			// Condicion de aceptacion.
			if (delta < 0 || ((double) rand() / (RAND_MAX)) < exp(-delta / T)) {

				sOpt = sAct->clone();

				if (sMejor->cost > sOpt->cost)
					sMejor = sOpt;

				a++;
			}
			delete sAct;
			k++;
		}

		i++;
		T *= alpha;
		K *= betha;
	}
	sMejor->numIter = i;
	sMejor->iniCost = is->cost;
	return sMejor;
}
